#include "Game.h"

IGame* createGame( HINSTANCE hInst, HWND hWnd )
{
	return new Game( hInst, hWnd );
}

Game::Game( HINSTANCE hInst, HWND hWnd ) :
	m_input( hInst, hWnd ),
	m_playerBody(), m_playerFollower()
{
	m_playerFollower.invLocalInertia = 10*identity33();
	m_playerFollower.invMass = 5;

	// initialize camera
	m_camera.hand = Camera::RIGHTHANDED;

	m_camera.eye = float3( 0, 0, 20.f );
	m_camera.at = float3( 0, 0, 0 );
	m_camera.up = float3( 0, 1, 0 );

	m_camera.projectionType = Camera::PERSPECTIVE_FOV;
	m_camera.perspectiveFov.fovy = D3DXToRadian(45.f);
	m_camera.perspectiveFov.aspect = 1024.f/768.f;

	m_camera.zn = 1.f;
	m_camera.zf = 100.f;

	// initialize polygons
	m_playerPoly.push_back( float3( 0.2, -0.5, 0 ) );
	m_playerPoly.push_back( float3( 0, 0.5, 0 ) );
	m_playerPoly.push_back( float3( -0.2, -0.5, 0 ) );

	m_collisionPoly.push_back( float3( +5, +0, 0 ) );
	m_collisionPoly.push_back( float3( +3, +2, 0 ) );
	m_collisionPoly.push_back( float3( +3, -2, 0 ) );
}

void Game::onCreateGraphics( D3DDevice device )
{
	m_d3dDevice = device;
	m_geomEffect.initialize( m_d3dDevice );
	m_triangle.initialize( m_d3dDevice, m_geomEffect );
	m_collisionTriangle.initialize( m_d3dDevice, m_geomEffect );
	m_overlapGeom.initialize( m_d3dDevice, m_geomEffect );

	Geom::Vertices triangleVertices;
	float3 head( 0, 0.5, 0 );
	float3 left( -0.2, -0.5, 0 );
	float3 right( 0.4, -0.5, 0 );
	triangleVertices.push_back( right );
	triangleVertices.push_back( head );
	triangleVertices.push_back( left );
	
	m_triangle.setVertices( triangleVertices );

	Geom::Vertices collisionVertices;
	collisionVertices.push_back( float3( +5, +0, 0 ) );
	collisionVertices.push_back( float3( +3, +2, 0 ) );
	collisionVertices.push_back( float3( +3, -2, 0 ) );

	m_collisionTriangle.setVertices( collisionVertices );
}

void Game::onFrameRender( float dt )
{
	float44 world, view, proj;
	float44 viewProj;

	view = m_camera.view();
	proj = m_camera.projection();

	viewProj = view * proj;

	m_geomEffect.setWorldViewProj( m_playerBody.world() * viewProj );
	m_geomEffect.setColor( float4( 1.0f, 1.0f, 64.f/256.f, 1.0f ) );
	m_triangle.render();

	m_geomEffect.setWorldViewProj( m_playerFollower.world() * viewProj );
	m_geomEffect.setColor( float4( 64.f/256.f, 1.0f, 64.f/256.f, 1.0f ) );
	m_triangle.render();

	m_geomEffect.setWorldViewProj( /*identity() * */viewProj );
	m_geomEffect.setColor( float4( 1.0f, 0.5f, 0.3f, 1.0f ) );
	m_collisionTriangle.render();

	m_geomEffect.setWorldViewProj( /*identity() * */viewProj );
	m_geomEffect.setColor( float4( 1.0f, 0.1f, 0.1f, 1.0f ) );
	m_overlapGeom.render();
}

void Game::onFrameMove( float dt )
{
	IInput::KEYSTATE keyState;
	keyState = m_input.keyState();

	if( keyState.keys[DIK_UP] & 0x80 )
		m_playerBody.addForceLocal( float3(0, 1, 0) );

	if( keyState.keys[DIK_LEFT] & 0x80 )
		m_playerBody.addTorqueLocal( float3(0, 0, +3) );
	if( keyState.keys[DIK_RIGHT] & 0x80 )
		m_playerBody.addTorqueLocal( float3(0, 0, -3) );

	 m_playerBody.step( dt );
	 m_playerBody.resetForces();

	 float3 playerJoint = transformCoord( float3(0, -0.5, 0 ), m_playerBody.world() );
	 float3 followerJoint = transformCoord( float3( 0, 0.5, 0 ), m_playerFollower.world() );

	 m_playerFollower.displace( playerJoint - followerJoint );

	 m_playerFollower.resolveRevolute( m_playerBody, playerJoint );

	 m_playerFollower.step( dt );
	 m_playerFollower.resetForces();

#if 0
	 Contact contact;
	 if( intersect( m_collisionPoly, transform( m_playerPoly, m_playerBody.world() ), contact ) )
	 {
		 m_playerBody.displace( contact.seperation );
		 RigidBody fixed;
		 fixed.invMass = 0;
		 fixed.invLocalInertia = zero33();
		 
		 fixed.resolveCollision( m_playerBody, contact.point, contact.axis, 0.5, 0 );
	 }
#endif

#if 0
	 poly::Polygon trnPlayer = transform( m_playerPoly, m_playerBody.world() );
	 m_overlapGeom.setVertices( conjunction( m_collisionPoly, trnPlayer ) );
#endif
}

void Game::onResetGraphics(D3DDevice device)
{
	m_d3dDevice = device;
}

void Game::onDestroyGraphics()
{
	m_geomEffect.destroy();
	m_triangle.destroy();
}
